const fs = require('fs');
const path = require('path');
const { Task, TaskStatus } = require('../models/task');

/**
 * 队列管理器
 * 负责管理下载任务队列，支持持久化存储
 */
class QueueManager {
  constructor(storageFile = null) {
    this.storageFile = storageFile || path.join(__dirname, '../storage/queue.json');
    this.queue = new Map(); // 使用Map保证插入顺序
    this.processing = false;
    this.currentTask = null;
    this.loadQueue();
  }

  /**
   * 从文件加载队列
   */
  loadQueue() {
    try {
      if (fs.existsSync(this.storageFile)) {
        const data = fs.readFileSync(this.storageFile, 'utf8');
        const queueData = JSON.parse(data);

        // 恢复任务实例
        for (const taskData of queueData.tasks || []) {
          const task = Task.fromJSON(taskData);
          this.queue.set(task.id, task);
        }

        this.processing = queueData.processing || false;
        this.currentTask = queueData.currentTask || null;

        console.log(`📁 加载队列: ${this.queue.size} 个任务`);
      }
    } catch (error) {
      console.error('❌ 加载队列失败:', error.message);
      this.queue = new Map();
    }
  }

  /**
   * 保存队列到文件
   */
  saveQueue() {
    try {
      const queueData = {
        tasks: Array.from(this.queue.values()).map(task => task.toJSON()),
        processing: this.processing,
        currentTask: this.currentTask,
        savedAt: new Date().toISOString()
      };

      fs.writeFileSync(this.storageFile, JSON.stringify(queueData, null, 2));
    } catch (error) {
      console.error('❌ 保存队列失败:', error.message);
    }
  }

  /**
   * 添加任务到队列
   * @param {string} url - 下载链接
   * @param {string} customFileName - 自定义文件名（可选）
   * @returns {Task} 创建的任务
   */
  addTask(url, customFileName = null) {
    // 检查是否已存在相同URL的任务
    const existingTask = this.findTaskByUrl(url);
    if (existingTask && (existingTask.status === TaskStatus.PENDING || existingTask.status === TaskStatus.DOWNLOADING)) {
      throw new Error('该URL的下载任务已存在且未完成');
    }

    const task = new Task(url, customFileName);
    this.queue.set(task.id, task);
    this.saveQueue();

    console.log(`➕ 添加任务: ${task.id} - ${url}`);
    return task;
  }

  /**
   * 根据URL查找任务
   * @param {string} url - 下载链接
   * @returns {Task|null}
   */
  findTaskByUrl(url) {
    for (const task of this.queue.values()) {
      if (task.url === url) {
        return task;
      }
    }
    return null;
  }

  /**
   * 根据ID获取任务
   * @param {string} taskId - 任务ID
   * @returns {Task|null}
   */
  getTask(taskId) {
    return this.queue.get(taskId) || null;
  }

  /**
   * 获取下一个待处理任务
   * @returns {Task|null}
   */
  getNextTask() {
    for (const task of this.queue.values()) {
      if (task.status === TaskStatus.PENDING) {
        return task;
      }
    }
    return null;
  }

  /**
   * 获取队列中所有任务
   * @returns {Array<Task>}
   */
  getAllTasks() {
    return Array.from(this.queue.values());
  }

  /**
   * 获取指定状态的任务
   * @param {string} status - 任务状态
   * @returns {Array<Task>}
   */
  getTasksByStatus(status) {
    return Array.from(this.queue.values()).filter(task => task.status === status);
  }

  /**
   * 删除任务
   * @param {string} taskId - 任务ID
   * @returns {boolean} 是否删除成功
   */
  removeTask(taskId) {
    const task = this.queue.get(taskId);
    if (!task) {
      return false;
    }

    // 如果是当前正在处理的任务，不能删除
    if (task.status === TaskStatus.DOWNLOADING) {
      throw new Error('无法删除正在下载的任务');
    }

    this.queue.delete(taskId);
    this.saveQueue();

    console.log(`🗑️  删除任务: ${taskId}`);
    return true;
  }

  /**
   * 取消任务
   * @param {string} taskId - 任务ID
   * @returns {boolean} 是否取消成功
   */
  cancelTask(taskId) {
    const task = this.queue.get(taskId);
    if (!task) {
      return false;
    }

    if (task.status === TaskStatus.COMPLETED) {
      throw new Error('无法取消已完成的任务');
    }

    task.updateStatus(TaskStatus.CANCELLED);
    this.saveQueue();

    console.log(`❌ 取消任务: ${taskId}`);
    return true;
  }

  /**
   * 重试失败的任务
   * @param {string} taskId - 任务ID
   * @returns {boolean} 是否重试成功
   */
  retryTask(taskId) {
    const task = this.queue.get(taskId);
    if (!task) {
      return false;
    }

    if (!task.canRetry()) {
      throw new Error('任务无法重试');
    }

    task.incrementRetry();
    task.reset();
    this.saveQueue();

    console.log(`🔄 重试任务: ${taskId} (第${task.retryCount}次)`);
    return true;
  }

  /**
   * 更新任务状态
   * @param {string} taskId - 任务ID
   * @param {string} status - 新状态
   * @param {Object} data - 附加数据
   */
  updateTask(taskId, status, data = {}) {
    const task = this.queue.get(taskId);
    if (task) {
      task.updateStatus(status, data);
      this.saveQueue();
    }
  }

  /**
   * 更新任务进度
   * @param {string} taskId - 任务ID
   * @param {number} downloadedSize - 已下载大小
   * @param {number} totalSize - 总大小
   * @param {number} progress - 进度百分比
   */
  updateTaskProgress(taskId, downloadedSize, totalSize, progress) {
    const task = this.queue.get(taskId);
    if (task) {
      task.updateProgress(downloadedSize, totalSize, progress);
      // 进度更新频繁，不每次都保存
      if (Math.floor(progress) % 10 === 0) {
        this.saveQueue();
      }
    }
  }

  /**
   * 获取队列统计信息
   * @returns {Object}
   */
  getStats() {
    const all = this.getAllTasks();
    const stats = {
      total: all.length,
      pending: 0,
      downloading: 0,
      completed: 0,
      failed: 0,
      cancelled: 0
    };

    for (const task of all) {
      stats[task.status]++;
    }

    return stats;
  }

  /**
   * 清理已完成的任务
   * @param {number} maxAge - 最大保留天数（默认7天）
   */
  cleanupCompletedTasks(maxAge = 7) {
    const cutoffDate = new Date();
    cutoffDate.setDate(cutoffDate.getDate() - maxAge);

    let cleaned = 0;
    for (const [taskId, task] of this.queue.entries()) {
      if ((task.status === TaskStatus.COMPLETED || task.status === TaskStatus.FAILED) &&
        task.completedAt && task.completedAt < cutoffDate) {
        this.queue.delete(taskId);
        cleaned++;
      }
    }

    if (cleaned > 0) {
      this.saveQueue();
      console.log(`🧹 清理了 ${cleaned} 个过期任务`);
    }

    return cleaned;
  }

  /**
   * 获取队列状态摘要
   * @returns {Object}
   */
  getQueueSummary() {
    const stats = this.getStats();
    const currentTask = this.currentTask ? this.getTask(this.currentTask) : null;

    return {
      stats,
      processing: this.processing,
      currentTask: currentTask ? currentTask.getSummary() : null,
      queueLength: stats.pending,
      lastSaved: fs.existsSync(this.storageFile) ?
        fs.statSync(this.storageFile).mtime : null
    };
  }

  /**
   * 设置当前处理任务
   * @param {string} taskId - 任务ID
   */
  setCurrentTask(taskId) {
    this.currentTask = taskId;
    this.processing = !!taskId;
    this.saveQueue();
  }

  /**
   * 清除当前处理任务
   */
  clearCurrentTask() {
    this.currentTask = null;
    this.processing = false;
    this.saveQueue();
  }
}

module.exports = QueueManager;
